home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Magnum One
/
Magnum One (Mid-American Digital) (Disc Manufacturing).iso
/
d19
/
zdoor33.arc
/
NOSCROLL.ASM
< prev
next >
Wrap
Assembly Source File
|
1989-03-12
|
26KB
|
586 lines
page 77,132
CSeg Segment Para Public 'CODE'
Assume CS:CSeg,DS:CSeg,ES:CSeg
;┌────────────────────────────────────────────────────────────────────────────┐
;│ NoScroll.Asm │
;│ │
;│ A program to restrict the scrolling of output to the first 22 rows of │
;│ the screen. │
;│ │
;│ by R. P. Byrne - 1/11/89 │
;│ │
;│ Syntax: NoScroll [n] │
;│ │
;│ where n represents the last row on the screen that will be allowed to │
;│ scroll (if not specified, defaults to line 22) │
;│ │
;│ First call installs this utility, second call de-installs it │
;│ │
;│ │
;│ Credit where due: This program is based on concepts implemented by │
;│ Sam Smith for his Prons.Asm program. │
;└────────────────────────────────────────────────────────────────────────────┘
;============ *** PSP DATA LABELS *** ==========================================
org 80h ;INTERESTING PSP STUFF STARTS HERE
Parm_Length db ? ;LENGTH OF CMD LINE PARAMETERS
Parameters label byte ;THE COMMAND PARAMETERS ARE HERE
;===============================================================================
org 100h
Entry_Point: jmp EntryPt
;┌─────────────────────────────────────────────────────────────────────────────┐
;│ Data Storage Area │
;└─────────────────────────────────────────────────────────────────────────────┘
MaxRow db 21 ;(last scrollable row on screen) - 1
ProgramID db 'NoScroll by R. P. Byrne 1/11/89','$'
PgmIDLen equ $-ProgramID
OldInt10 dd ? ;the "real" bios video isr
OldInt21 dd ? ;the "real" dos function call isr
DummyReturn dw ? ;just a dummy variable used for stack adjustment
;┌─────────────────────────────────────────────────────────────────────────────┐
;│ Commonly called subroutines │
;└─────────────────────────────────────────────────────────────────────────────┘
UseOldInt10 Proc Near
push bp ;save bp just in case machine has old bios bug
pushf ;push flags to simulate an int instruction
call dword ptr cs:OldInt10 ;call bios video service
pop bp ;restore base pointer
ret ;return to caller
UseOldInt10 EndP
;┌─────────────────────────────────────────────────────────────────────────────┐
;│ Interrupt service routine (ISR) for Bios Video interrupt │
;└─────────────────────────────────────────────────────────────────────────────┘
Entry10 Proc far
assume ds:nothing, es:nothing, ss:nothing
sti
Chk0E: cmp ah,0Eh ;TTY write request?
jnz Chk06 ;no, go check for scroll request
cmp al,0Ah ;yes. is character a linefeed?
jnz AllOther ;nope ... no special treatment
call ChkTTY ;yup ... go take care of it
jmp short AllDone
Chk06: cmp ah,06h ;scroll page request?
jnz Chk02 ;no, go check for cursor move request
call ChkScroll ;yes, go take care of it
jmp short AllDone
Chk02: cmp ah,02h ;set pos request?
jnz AllOther ;no ... no special treatment
cmp dh,MaxRow ;request outside of window?
jbe AllOther ;nope ...
call ChkCursor ;yup ... go fix it
jmp short AllDone
AllOther: call UseOldInt10 ;call the "real" int 10h for service
AllDone: IRet ;Return to requestor of video service
Entry10 EndP
;──────[ Int 10h, function 0Eh - TTY write request ]──────────────────────────
ChkTTY Proc near
push ax
push bx
push cx
push dx
push si
push di
push ds
push es
push bp
push ax ;save ax
mov ah,03h ;call Bios to get the current
call UseOldInt10 ; cursor position into DX
pop ax ;restore ax
ChkNewRow: inc dh ;adjust row number for LF
cmp dh,MaxRow ;outside the window?
jg ScrollIt ;yes ... scroll the window
call UseOldInt10 ;no, let "real" bios handle it
jmp TTY_GoBack
ScrollIt: mov ah,06h ;video scroll up function
mov al,1 ;only scroll 1 line
xor cx,cx ;upper left corner = 0,0
mov dh,MaxRow ;
mov dl,4Fh ;lower right corner = MaxRow,79
mov bh,07h ;use white on black attribute
call UseOldInt10 ;Call Int 10h
MovCursor: mov bh,0 ;video page 0
mov ah,2 ;set cursor function
mov dh,MaxRow ;1st col of last row
mov dl,0 ; ie. MaxRow,0
call UseOldInt10 ;move the cursor
TTY_GoBack: pop bp
pop es
pop ds
pop di
pop si
pop dx
pop cx
pop bx
pop ax
ret
ChkTTY EndP
;──────[ Int 10h, function 6 - scroll page up request ]───────────────────────
ChkScroll Proc near
cmp ch,MaxRow ;row of UL corner <= max?
jbe ULisOK ;yes, go check LR corner
mov ch,MaxRow ;no, adjust it
ULisOK: cmp dh,MaxRow ;row of LR corner <= max?
jbe LRisOK ;yes, no adjustment needed
mov dh,MaxRow ;no, adjust it
LRisOK: call UseOldInt10 ;let old ISR do the scroll
ret
ChkScroll EndP
;──────[ Int 10h, function 2 - set cursor position request ]──────────────────
ChkCursor Proc near
push ax ;Before we fix, scroll the screen by
push bx ; (row requested - MaxRow) rows
push cx ;
push dx ;save cursor pos
mov ah,06h ;scroll page up function
mov al,dh ;calculate number of rows to scroll
sub al,MaxRow ;
xor cx,cx ;UL corner = 0,0
mov dh,MaxRow ;lower right corner = 21,79
mov dl,4Fh ;
mov bh,07h ;use white on black attribute
call UseOldInt10 ;call int 10h
pop dx ;restore cursor pos in dx
pop cx ;
pop bx ;
pop ax ;
mov dh,MaxRow ;Plug row number
CursorOk: call UseOldInt10 ;Let "real" bios move cursor
ret
ChkCursor EndP
;┌─────────────────────────────────────────────────────────────────────────────┐
;│ Interrupt service routine (ISR) for Dos function request interrupt │
;└─────────────────────────────────────────────────────────────────────────────┘
Entry21 Proc far
assume ds:nothing, es:nothing, ss:nothing
sti
Chk09D: cmp ah,9
jnz Chk02D
call ChkString
jmp short AlldoneD
Chk02D: cmp ah,2 ;console output request?
jnz Chk40D ;no, go check for file/device write
cmp dl,0Ah ;yes. is character a linefeed?
jnz AllOtherD ;nope ... no special treatment
call ChkConOut ;yup ... go take care of it
jmp short AllDoneD
Chk40D: cmp ah,40h ;device output request?
jnz AllOtherD ;no ... no special treatment
cmp bx,1 ;standard output device?
jne ChkStdErr ;no, see if std err
jcxz AllOtherD ;if char count 0, no special treatment
call ChkWrite ;yes, go watch for linefeeds ...
jmp short AllDoneD ; and then exit
ChkStderr: cmp bx,2 ;standard error device?
jne AllOtherD ;no, no special treatment
call Chkwrite ;yup ... go handle the request
jmp short AllDoneD
AllOtherD: jmp dword ptr cs:OldInt21 ;jump into dos
AllDoneD: Retf 2 ;Return to requestor of service
Entry21 EndP
;──────[ Int 21h, function 09h - write string to console ]────────────────────
ChkString Proc near
;
; Calling program has requested a write to either the standard output device or
; the standard error device
;
push bx ;preserve all registers that don't
push cx ; return status information
push dx ; for the call
push si ;
push di ; CF acts as an error flag
push ds ; AX returns number of bytes written
push es ;
push bp ;
mov si,dx ;ds:si --> string to display
OneChar: lodsb ;get a byte to display
cmp al,'$' ;end of string?
jz NoMore ;yes...time to quit
mov dl,al ;load dl for dos call
mov ah,02h ;dos console output function
int 21h ;display one character
jmp short OneChar ;repeat for all characters in buffer
NoMore: pop bp
pop es
pop ds
pop di
pop si
pop dx
pop cx
pop bx
clc ;clear CF for return
ret
ChkString EndP
;──────[ Int 21h, function 40h - write to file/device ]───────────────────────
ChkWrite Proc near
;
; Calling program has requested a write to either the standard output device or
; the standard error device
;
push bx ;preserve all registers that don't
push cx ; return status information
push dx ; for the call
push si ;
push di ; CF acts as an error flag
push ds ; AX returns number of bytes written
push es ;
push bp ;
mov si,dx ;ds:si --> string to display
DisplayOne: lodsb ;get a byte to display
mov dl,al ;
mov ah,02h ;dos console output function
int 21h ;display one character
loop DisplayOne ;repeat for all characters in buffer
pop bp
pop es
pop ds
pop di
pop si
pop dx
pop cx
pop bx
clc ;clear CF for return
mov ax,cx ;set byte count for return
ret
ChkWrite EndP
;──────[ Int 21h, function 02h - write to console ]───────────────────────────
ChkConOut Proc near
; calling program has requested a linefeed be sent to either
; the standard output or standard error device. Use int 10h
; to satisfy the request while checking for scroll out of
; window
push ax
push bx
push cx
push dx
push si
push di
push ds
push es
push bp
mov ax,0E0Ah
int 10h
pop bp
pop es
pop ds
pop di
pop si
pop dx
pop cx
pop bx
pop ax
clc ;clear carry for return
ret
ChkConOut EndP
;┌─────────────────────────────────────────────────────────────────────────────┐
;│ Program installation section │
;└─────────────────────────────────────────────────────────────────────────────┘
EntryPt: assume cs:CSeg, ds:CSeg, es:CSeg, ss:CSeg
mov ah,35h ;function 35h retrieves interrupt vector
mov al,10h ;we're interested in interrupt 10h
int 21h ;get int 10 vector into es:bx
mov di,offset ProgramID ;es:di --> program id area of
mov si,di ; current int 10h isr, ds:si -->
mov cx,PgmIDLen ; pgm id area of this pgm.
repe cmpsb ;check for matching pgm id's
je Uninstall ;program ID string found in int 10 ISR
jmp FirstTime ;go install this program
Uninstall: ;on entry, es contains seg. of isr to be removed (put there
;by call to dos function 35h)
push ds ;save our data seg for final message
lds dx,es:OldInt10 ;load addr of original isr into ds:dx
mov ah,25h ;set interrupt vector
mov al,10h ;reset int 10h isr back to where it was ...
int 21h ; before user installed NoScroll
;
lds dx,es:OldInt21 ;load addr of original isr into ds:dx
mov ah,25h ;set interrupt vector
mov al,21h ;reset int 21h isr back to where it was ...
int 21h ; before user installed NoScroll
;
push es ;save seg of isr
mov ax,es ;transfer isr's code segment addr ...
mov ds,ax ; to the data seg reg
mov si,2Ch ;ds:si --> segment addr of isr's environment
lodsw ;get env seg of tsr process ...
mov es,ax ; load into es for dos call ...
mov ah,49h ; and deallocate it
int 21h ;
pop es ;restore code seg of isr ...
mov ah,49h ; and deallocate it
int 21h ;
pop ds ;restore our data segment register
mov ah,9
mov dx,offset ProgramId
int 21h ;start explaining
mov ah,9
mov dx,offset RemovMsg
int 21h ;explain
int 20h ;we're done ... exit to dos
FirstTime: assume es:nothing
xor ch,ch
mov cl,Parm_Length ;length of command line parameters
mov si,offset Parameters
jcxz Defaults ;if no parameters, then use default maxrow
Strip_L: lodsb
cmp al,' ' ;skip all leading spaces ...
jz IgnoreCh
cmp al,09 ; ... and tab characters
jz IgnoreCh
jmp short GetParm
IgnoreCh: dec cx
jmp short Strip_L
GetParm: jcxz Defaults ;nothing there but white space
dec si ;ds:si ---> 1st non-blank char in cmd line
; cx = length of command line
call Ascii_To_Bin ;should return a valid binary number in bx
jnc ChkRange ;CF --> non-numeric data
jmp Syntax ; Show Syntax msg and exit w/out install
ChkRange: cmp bx,25 ;check row num. for valid range
jg BadRow ;if invalid, show error msg and exit w/out install
cmp bx,1
jl BadRow
dec bx ;Ok, valid rownum entered ... adjust to zero
mov MaxRow,bl ; relative coordinate and store for use
Defaults: mov ah,35h ;Get vector
mov al,10h ; for int 10h
int 21h
mov word ptr [OldInt10],bx ;and store in memory for later
mov word ptr [OldInt10+2],es ;store in OldInt10
mov ah,25h ;set new vector for ...
mov al,10h ; int 10h to use the routine at Entry10
mov dx,offset Entry10 ;ds:dx ---> new int 10 isr
int 21h
mov ah,35h ;Get vector
mov al,21h ; for int 21h
int 21h
mov word ptr [OldInt21],bx ;and store in memory for later
mov word ptr [OldInt21+2],es ;store in OldInt10
mov ah,25h ;set new vector for ...
mov al,21h ; int 21h to use the routine at Entry10
mov dx,offset Entry21 ;ds:dx ---> new int 21 isr
int 21h
mov ah,3 ;get cursor position
mov bh,0
int 10h
cmp dh,MaxRow
jb ShowMsg
mov ah,6 ;scroll up
mov al,1
mov cx,0 ;UL corner is 0,0
mov dh,MaxRow ;LR corner is
mov dl,4Fh ; MaxRow,79
int 10h
mov ah,2 ;set cursor position
mov dh,MaxRow
mov dl,0
int 10h
ShowMsg: mov ah,9
mov dx,offset ProgramId
int 21h ;start explaining
mov ah,9
mov dx,offset InstMsg ;explain
int 21h
mov dx,offset EntryPt ;last resident byte
int 27h ;go memory resident
BadRow: mov dx,offset ProgramId
mov ah,9
int 21h
mov dx,offset BadRowMsg
mov ah,9
int 21h
int 20h
Syntax: mov dx,offset ProgramId
mov ah,9
int 21h
mov dx,offset SyntaxMsg
mov ah,9
int 21h
int 20h
;┌─────────────────────────────────────────────────────────────────────────────┐
;│ Proc to convert ascii to binary for command line parsing │
;└─────────────────────────────────────────────────────────────────────────────┘
Ascii_To_Bin Proc near
;
; This procedure will convert a string of numbers in ASCII form to a
; binary number. Upon entry, SI points at the string and CX contains
; the length of that string.
; The resulting binary number is returned to the calling procedure via
; the BX register.
; Validation of the string is performed by this procedure. If an error
; is encountered (eg. an ASCII code representing a non-numeric character),
; the procedure will exit with the carry flag set. It is the
; responsibility of the calling procedure to issue error messages to
; the user.
; Strings are converted as follows:
; As each character in the string is fetched, it is converted to a
; binary number. The partial sum (kept in BX) is multiplied by 10.
; the fetched and converted digit is added to the partial sum.
;
PUSH AX
PUSH CX
PUSH SI
CMP CX,0 ;BE SURE THERE IS DATA TO PROCESS
JE A2B_ERROR ;IF NO DATA, EXIT WITH ERROR
XOR BX,BX ;INITIALIZE BX REGISTER TO ZERO
A2B_LOOP: XOR AX,AX ;INIT AX TO ZERO
LODSB ;GET 1 CHARACTER FROM THE STRING
CMP AL,30H ;LOWER LIMIT FOR NUM. CHAR.
JB A2B_ERROR
CMP AL,39H ;UPPER LIMIT FOR NUM. CHAR.
JA A2B_ERROR
SUB AL,30H ;CONVERT 1 DIGIT TO BINARY
XCHG AX,BX ;SWITCH REGISTERS
PUSH CX ;SAVE CHARS REMAINING
MOV CX,10 ;PARTIAL SUM MULTIPLIER
MUL CX ;MULTIPLY PARTIAL SUM BY 10
POP CX ;RESTORE CHARS REMAINING
JC A2B_ERROR ;CHECK FOR CARRY OUT OF AX
ADD BX,AX ;ADD PARTIAL SUM TO THE LAST DIGIT
JC A2B_ERROR ;CHECK FOR CARRY OUT OF BX
LOOP A2B_LOOP ;LOOP FOR ALL CHARS IN STRING
A2B_END: CLC ;CLEAR CARRY FLAG --> NO ERRORS
JMP A2B_EXIT ;AND EXIT
A2B_ERROR: STC ;SET CARRY FLAG --> ERROR FOUND
A2B_EXIT: POP SI
POP CX
POP AX
RET
ASCII_TO_BIN ENDP
;┌─────────────────────────────────────────────────────────────────────────────┐
;│ Additional, non-resident storage │
;└─────────────────────────────────────────────────────────────────────────────┘
InstMsg db ' installed.',0Dh,0Ah,'$'
RemovMsg db ' removed.',0Dh,0Ah,'$'
BadRowMsg db 0Dh,0Ah
db 'Row number out of range! Min=1, Max=25.'
db 0Dh,0Ah,'$'
SyntaxMsg db 0Dh,0Ah
db 'Usage: NoScroll [rownum]',0Dh,0Ah,0Dh,0Ah
db 'Where rownum specifies the number of the last unprotected row.'
db 0Dh,0Ah
db ' 1 <= rownum <= 25'
db 0Dh,0Ah
db ' If rownum is not specified, it will default to 22.'
db 0Dh,0Ah,'$'
;┌─────────────────────────────────────────────────────────────────────────────┐
;│ That's all folks! │
;└─────────────────────────────────────────────────────────────────────────────┘
CSeg EndS
end Entry_Point